#ifndef FLOW_CHART_H
#define FLOW_CHART_H

#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/transition.hpp>
#include <boost/statechart/custom_reaction.hpp>
#include <boost/mpl/list.hpp>
#include "pipe_module.h"
#include "MinuteTimer.h"

namespace mpl = boost::mpl;
using namespace boost::statechart;

class CProxyEventHandler;

class CProxy;

struct EvValidated : event<EvValidated>{};

struct EvServerAccepted : event<EvServerAccepted> {};

struct EvServerDisconnected : event<EvServerDisconnected> {};

struct DBCommState;

struct ValidateState;

struct GSCommState;

struct WaitConnectState;

class IEvents
{
public:
    virtual ~IEvents(){}

    virtual void OnRcvCliMessage(const char * message, uint32 message_length) const {}

    virtual void OnRcvSvrMessage(const char * message, uint32 message_length) const {}

    virtual void OnRcvPipeMessage(utility::network::PIPEID pipeID, const char * message, uint32 message_length) const {}

};

struct Machine : state_machine<Machine, ValidateState>
{
    Machine(CProxyEventHandler * );

    virtual void OnRcvCliMessage(const char * message, uint32 message_length)
    {
        state_cast<const IEvents & >().OnRcvCliMessage(message, message_length);
    }

    virtual void OnRcvSvrMessage(const char * message, uint32 message_length)
    {
        state_cast<const IEvents &>().OnRcvSvrMessage(message, message_length);
    }

    virtual void OnRcvPipeMessage(utility::network::PIPEID pipeID, const char * message, uint32 message_length)
    {
        state_cast<const IEvents &>().OnRcvPipeMessage(pipeID, message, message_length);
    }

    // send message to pipe
    void SendPipeMsg(utility::network::PIPEID pipeID, void * message, size_t message_length, bool isForward = true) const;

    // send message to client
    void SendClientMsg(void * message, size_t message_length) const;

    // send message to server
    void SendServerMsg(void * message, size_t message_length) const;

    void Disconnect();

    void ServerDisconnect();

    CProxy * GetProxy();
private:
    CProxyEventHandler * m_pProxyEventHandler;
};

struct ValidateState : simple_state<ValidateState, Machine>, public IEvents, public CMinuteTimerSubscriber
{
    typedef transition< EvValidated, DBCommState > reactions;

    ValidateState();

    ~ValidateState();

    virtual void OnRcvCliMessage(const char * message, uint32 message_length) const;

    virtual void OnTrigger(time_t);

    void OnValidate(uint32 nUsrID, uint32 nToken);

    void OnFailValidate();
private:
    time_t m_tStartTime;
    uint8 m_nFailTimes;
};

struct DBCommState : simple_state<DBCommState, Machine> , public IEvents, public CMinuteTimerSubscriber
{
    typedef transition<EvServerAccepted, GSCommState> reactions;

    DBCommState();

    ~DBCommState();

    virtual void OnRcvCliMessage(const char * message, uint32 message_length) const;

    virtual void OnRcvPipeMessage(utility::network::PIPEID pipeID, const char * message, uint32 message_length) const;

    virtual void OnTrigger(time_t);

    result react(const EvServerAccepted & ev);
private:
    time_t m_tStartTime;
};

struct GSCommState : simple_state<GSCommState, Machine>, public IEvents
{
    typedef transition<EvServerDisconnected, DBCommState> reactions;

    GSCommState();
    ~GSCommState();

    virtual void OnRcvCliMessage(const char * message, uint32 message_length) const;

    virtual void OnRcvSvrMessage(const char * message, uint32 message_length) const;
};

#endif
